package com.mall.controller;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.mall.Enum.Sex;
import com.mall.note.Limit;
import com.mall.pojo.Admin;
import com.mall.pojo.User;
import com.mall.service.IAdminService;
import com.mall.service.IUserService;
import com.mall.utils.R;
import com.mall.utils.ThreadLocalUtils;
import com.mall.vo.RegistryUserVo;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;

/**
 * 登录注册处理
 *
 * @author cxx
 */
@Slf4j
@RestController
@Validated
public class LoginController {
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private IUserService userService;
    @Resource
    private IAdminService adminService;
    @Resource
    private ThreadLocalUtils threadLocalUtils;

    /**
     * 用户登录
     *
     * @param userName 用户名
     * @param password 用户账号
     * @param code     验证码
     * @param codeId   验证码id
     * @return com.mall.utils.R<java.lang.String>
     * @author cxx
     * @date 2023/4/22 22:33
     */

    @PostMapping("/user/login")
    public R<Object> login(@RequestParam(name = "userName") String userName, @RequestParam(name = "password") String password, @RequestParam(name = "code") String code, @RequestParam(name = "codeId") String codeId) {
        String captcha;
        //判断验证码是否过期
        if (!redisTemplate.hasKey(codeId)) {
            return R.error("验证码错误!");
        }
        //获取放置在缓存中的验证码
        captcha = redisTemplate.opsForValue().get(codeId).toString();
        if (!captcha.equals(code.toLowerCase())) {
            return R.error("验证码错误!");
        }
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, DigestUtils.md5Hex(userName.getBytes())).and(i -> i.eq(User::getPassword, DigestUtils.md5Hex(password.getBytes())));
        //判断用户账号密码是否输入正确
        User one = userService.getOne(queryWrapper);

        if (ObjectUtils.isEmpty(one)) {
            return R.error("账号或密码错误!");
        }

        if (one.getStatus() != 1) {
            return R.error("账号被禁用，无法登录,请联系管理员!");
        }
        //创建updateWrapper修改用户最后一次的登录时间
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(User::getUsername, DigestUtils.md5Hex(userName.getBytes())).set(User::getLoadDate, LocalDateTime.now());
        StpUtil.login(one.getId());
        //登录成功后删除缓存在redis中的验证码
        redisTemplate.delete(codeId);
        log.error(StpUtil.getPermissionList(one.getId()).toString());
        log.error(StpUtil.getRoleList(one.getId()).toString());
        userService.update(updateWrapper);
        return R.success(StpUtil.getTokenInfo());

    }

    /**
     * 管理员登录
     *
     * @param userName 管理员账号
     * @param password 账号密码
     * @param code     验证码
     * @param codeId   验证码id
     * @return com.mall.utils.R<java.lang.String>
     * @author cxx
     * @date 2023/4/22 22:34
     */
    @Limit
    @PostMapping("/admin/login")
    public R<Object> adminLogin(@RequestParam(name = "userName") String userName, @RequestParam(name = "password") String password, @RequestParam(name = "code") String code, @RequestParam(name = "codeId") String codeId) {
        String captcha;
        if (!redisTemplate.hasKey(codeId)) {
            return R.error("验证码错误!");
        }
        captcha = redisTemplate.opsForValue().get(codeId).toString();
        if (!captcha.equals(code)) {
            return R.error("验证码错误!");
        }
        LambdaQueryWrapper<Admin> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Admin::getUsername, DigestUtils.md5Hex(userName.getBytes())).and(i -> i.eq(Admin::getPassword, DigestUtils.md5Hex(password.getBytes())));
        Admin one = adminService.getOne(queryWrapper);
        if (ObjectUtils.isNotEmpty(one)) {
            StpUtil.login(one.getId());
            //登录成功后删除缓存在redis中的验证码
            redisTemplate.delete(codeId);
            log.error(StpUtil.getPermissionList(one.getId()).toString());
            log.error(StpUtil.getRoleList(one.getId()).toString());
            return R.success(StpUtil.getTokenInfo());
        }
        return R.error("账号或密码错误!");
    }

    /**
     * 用户注册,性别传0或1,0女1男
     *
     * @param user 用户的各类信息,性别传0或1,0女1男
     * @return com.mall.utils.R<java.lang.String>
     * @author cxx
     * @date 2023/4/22 23:14
     */

    @PostMapping("/registry")
    public R<String> registry(@Valid @RequestBody RegistryUserVo user) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        user.setUsername(DigestUtils.md5Hex(user.getUsername().getBytes()));
        user.setPassword(DigestUtils.md5Hex(user.getPassword().getBytes()));
        wrapper.eq(User::getUsername, user.getUsername());
        User one = userService.getOne(wrapper);
        if (ObjectUtils.isNotEmpty(one)) {
            return R.error("注册失败,账号已经存在!");
        }
        if (!redisTemplate.hasKey("SMS-" + user.getPhone())) {
            return R.error("短信验证码已经过期!");
        }
        if (!user.getSmsCode().equals(redisTemplate.opsForValue().get("SMS-" + user.getPhone()).toString())) {
            return R.error("短信验证码错误!");
        }
        threadLocalUtils.set("用户注册");
        User user1 = new User();
        BeanUtils.copyProperties(user, user1);
        if (user.getSex() == 1) {
            user1.setSex(Sex.MAN);
        } else {
            user1.setSex(Sex.WOMAN);
        }
        userService.save(user1);
        redisTemplate.delete("SMS-" + user.getPhone());
        return R.success("注册成功!");
    }

    /**
     * 退出登录
     *
     * @return com.mall.utils.R<java.lang.String>
     * @author cxx
     * @date 2023/4/24 9:32
     */
    @PostMapping("/logout")
    public R<String> logout() {
        Long loginId = Long.valueOf(StpUtil.getLoginId().toString());
        log.error(loginId.toString());
        StpUtil.logout(loginId);
        return R.success("登出成功!");

    }

}
